#include "Recipe.h"
#include "Player.h"
#include "Ingredient.h"
#include "Game.h"
#include "StringLib.h"
#include "Util.h"
#include "Potion.h"

Recipe::Recipe(RecipeType type) {
	m_recipe = new std::list<RecipeItem*>();
	m_type = type;
	m_currentItem = 0;
	switch(m_type) {
	case RT_POTION_HEAL:
		addRecipeItem(createRecipeItem("alch1", TH_INGREDIENT_TYPE, IT_ALCH_RAT_TAIL, 1));
		addRecipeItem(createRecipeItem("alch2", TH_INGREDIENT_TYPE, IT_ALCH_NEWT_EYE, 1));
		addRecipeItem(createRecipeItem("herb1", TH_INGREDIENT_TYPE, IT_HERB_PAPRIKA, 1));
		break;
	}
}

Recipe::~Recipe() {
	for(std::list<RecipeItem*>::iterator iter = m_recipe->begin(); iter != m_recipe->end(); iter++)
		delete (*iter);
	delete m_recipe;
}

void Recipe::addRecipeItem(RecipeItem* item) {
	m_recipe->push_back(item);
	m_map[item->name] = item;
}

RecipeItem* Recipe::createRecipeItem(std::string name, TypeHierarchy typeCategory, int type, int numRequired, bool required) {
	RecipeItem* recipeItem = new RecipeItem;
	recipeItem->name = name;
	recipeItem->typeCategory = typeCategory;
	recipeItem->type = type;
	recipeItem->numRequired = numRequired;
	recipeItem->required = required;
	return recipeItem;
}

void Recipe::craft(Player* player) {
	std::list<Item*> items;
	int status = 1, numItems = 0;
	for(std::map<RecipeItem*, std::list<Item*>>::iterator iter = m_selectedItems.begin(); iter != m_selectedItems.end(); iter++) {
		for(std::list<Item*>::iterator iter2 = (*iter).second.begin(); iter2 != (*iter).second.begin(); iter2++) {
			numItems++;
			switch((*iter2)->getStatus()) {
			case CURSED:
				status--;
				break;
			case UNCURSED:
				break;
			case BLESSED:
				status++;
				break;
			}
		}
	}
	switch(m_type) {
	case RT_POTION_HEAL: {
		Potion* potion = new Potion(PT_HEALING, std::max(1, status));
		if(status <= 0 && rand(2))
			potion->setStatus(CURSED, true);
		else if(status-1 >= numItems/2 && rand(2))
			potion->setStatus(BLESSED, true);
		items.push_back(potion);
		break;
	}
	}
	for(std::map<RecipeItem*, std::list<Item*>>::iterator iter = m_selectedItems.begin(); iter != m_selectedItems.end(); iter++) {
		for(std::list<Item*>::iterator iter2 = (*iter).second.begin(); iter2 != (*iter).second.end(); iter2++) {
			(*iter2)->reduceStackCount(1, true, g_player->getInventory());
		}
		(*iter).second.clear();
	}
	for(std::list<Item*>::iterator iter = items.begin(); iter != items.end(); iter++) {
		g_textLog->addLine(g_stringLib->getTextString(ST_CRAFT_ITEM, (*iter)->getColoredName().c_str()));
		player->forceItemInInventory(*iter);
	}
	m_currentItem = 0;
	g_player->modifyTurnCounter(DEFAULT_TURN_LENGTH * 3);
}

RecipeItem* Recipe::getRecipeItem(int num) const {
	std::list<RecipeItem*>::iterator iter = m_recipe->begin();
	std::advance(iter, num);
	return *iter;
}

void Recipe::selectItem(Item* item) {
	RecipeItem* recipeItem = getRecipeItem(m_currentItem);
	if(item->getType(recipeItem->typeCategory) != recipeItem->type) return;
	m_selectedItems[recipeItem].push_back(item);
	if(recipeItem->numRequired == m_selectedItems[recipeItem].size())
		m_currentItem++;
}

Item* Recipe::getSelectedItem(std::string name) const {
	if(m_selectedItems.count(m_map.at(name)) > 0 && m_selectedItems.at(m_map.at(name)).size() > 0)
		return *(m_selectedItems.at(m_map.at(name)).begin());
	return NULL;
}

bool Recipe::canCraft(const Player* player) const {
	bool canCraft = true;
	RecipeItem* item = NULL;
	for(std::list<RecipeItem*>::const_iterator iter = m_recipe->begin(); iter != m_recipe->end(); iter++) {
		item = *iter;
		if(item->required) {
			if(!player->inventoryContains(item->typeCategory, item->type, item->numRequired))
				canCraft = false;
		}
	}
	return canCraft;
}

void Recipe::clearSelectedItems() {
	m_currentItem = 0;
	for(std::map<RecipeItem*, std::list<Item*>>::iterator iter = m_selectedItems.begin(); iter != m_selectedItems.end(); iter++) {
		(*iter).second.clear();
	}
}
